package com.juitar.base;

public class SimpleFingering {

    private int length;
    private int firstFret;
    private int mutedStrings;
    protected final int[] fingering;

    public SimpleFingering(int[] fingering) {
        this.fingering = fingering;
        metrics();
    }

    
    /**
     * Creates fingering from string, like this one - "x 3 2 0 1 0".
     * @param fing string fingering representation
     */
    public SimpleFingering(String fing) {
        fing = fing.trim();
        String[] frets = fing.split(" ");
        fingering = new int[frets.length];
        int i = fingering.length;
        while (--i >= 0) {
            try {
                fingering[i] = Integer.valueOf(frets[i]).intValue();
            } catch (Exception e) {
                fingering[i] = -1;
            }
        }
        metrics();
    }

    protected void metrics() {
        // Calculate fingering metrics
        int min = Integer.MAX_VALUE;
        int max = Integer.MIN_VALUE;
        for (int i = 0; i < fingering.length; i++) {
            if (fingering[i] > 0) {
                if (fingering[i] > max) {
                    max = fingering[i];
                }
                if (fingering[i] < min) {
                    min = fingering[i];
                }
            }

            if (fingering[i] < 0) {
                mutedStrings++;
            }
        }

        if (min == Integer.MAX_VALUE && max == Integer.MIN_VALUE) {
            length = 0;
        } else {
            length = max - min + 1;
        }

        firstFret = (min == Integer.MAX_VALUE) ? 0 : min;
    }

    /**
     * @return total number of strings for this fingering.
     */
    public int strings() {
        return fingering.length;
    }

    /**
     * @param string
     * @return fret for the given string
     */
    public int getFret(int string) {
        return fingering[string];
    }

    public int length() {
        return length;
    }

    public int getFirstFret() {
        return firstFret;
    }

    /**
     * @return number of muted strings in this fingering
     */
    public int numOfMutedStrings() {
        return mutedStrings;
    }

    public int distance(SimpleFingering another) {
        int result = 0;
        for (int i = 0; i < fingering.length; i++) {
            if (fingering[i] > 0 && another.fingering[i] > 0) {
                result += Math.abs(fingering[i] - another.fingering[i]);
            }
        }
        return result;
    }

    public String toString() {
        String ret = "";
        int i = fingering.length;
        while (--i >= 0) {
            if (fingering[i] >= 0) {
                ret += fingering[i] + " ";
            } else {
                ret += "x ";
            }
        }
        return ret.trim();
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj) { return true; }
        SimpleFingering f = (SimpleFingering) obj;
        for (int i = 0; i < fingering.length; i++) {
            if (fingering[i] != f.fingering[i]) { return false; }
        }
        return true;
    }

    @Override
    public int hashCode() {
        int result = 0;
        int factor = 1;
        for (int i = 0; i < fingering.length; i++) {
            result += fingering[i] * factor;
            factor *= 16;
        }
        return result;
    }

}
